<template>
  <el-form-item ref="formItemRef" v-bind="computedFormItemBind">
    <template v-if="labelNode || slots.label" #label>
      <template v-if="labelNode">
        <component :is="excuteCmp(labelNode)"></component>
      </template>
      <slot v-else name="label"></slot>
    </template>
    <template v-if="errorNode || slots.error" #error>
      <template v-if="errorNode">
        <component :is="excuteCmp(errorNode)"></component>
      </template>
      <slot v-else name="error"></slot>
    </template>
    <template v-if="computedContent">
      <component :is="computedContent" v-bind="computedContentBind" v-model="computedModel[prop || '']"></component>
    </template>
    <slot v-else></slot>
  </el-form-item>
</template>
<script setup lang="ts">

import {computed, ref, useAttrs, VNode} from 'vue'
import component from './component'

const attrs = useAttrs()
const slots = defineSlots<{
  label: any
  error: any
  default: any
}>()
type ItemProps = {
  prop?: string
  model?: Record<string, any>
  type?: string
  /** label插槽 */
  labelNode?: () => VNode
  /** error插槽 */
  errorNode?: () => VNode
  /**内容区域 */
  contentOption?: {
    /**内容类型 */
    type?: string | ((...args:any) => string)
    /**类型组件绑定的属性 */
    bind?: () => any
    /**自定义节点 */
    customNode?: () => VNode
  }
}

const props = withDefaults(defineProps<ItemProps>(), {})

const formItemRef = ref()


const computedModel = computed(() => {
  return props.model || {}
})

const computedFormItemBind = computed(() => {
  const bind = {...props, ...attrs}
  delete bind.labelNode
  delete bind.errorNode
  delete bind.contentOption
  return bind
})

const computedContent = computed(() => {
  if (props.contentOption) {
    if (props.contentOption.customNode) {
      return {
        render () {
          return props.contentOption && props.contentOption.customNode && props.contentOption.customNode()
        }
      }
    } else {
      return component[excuteN(props.contentOption.type)]
    }
  }
  return ''
})

const computedContentBind = computed(() => {
  if (props.contentOption) {
    if (props.contentOption.bind) {
      return props.contentOption.bind()
    }
  }
  return {}
})

const excuteN = (ex:any) => {
  if (!ex) return
  if (typeof ex === 'string') {
    return ex
  } else {
    return ex()
  }
}

const excuteCmp = (ex:any) => {
  return ex()
}

</script>
<style lang="scss" scoped>
</style>